package cn.iocoder.boot.service.impl.supplier;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.iocoder.boot.entity.ComponentPrice;
import cn.iocoder.boot.entity.ComponentStock;
import cn.iocoder.boot.enums.SupplierCodeEnum;
import cn.iocoder.boot.service.CallLimitService;
import cn.iocoder.boot.service.ComponentPriceService;
import cn.iocoder.boot.service.ComponentStockService;
import cn.iocoder.boot.service.HttpRequestLogService;
import cn.iocoder.boot.service.impl.SalePriceConfigServiceImpl;
import cn.iocoder.boot.utils.MessageUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
@DS("master")
@Slf4j
public class SHTServiceImpl {

    private static final String TOKEN_KEY = "supplier:shttoken";
    private static final String TOKEN_URL = "http://t.bomman.com/api/mall-auth/externalAuth/token";
    private static final String QUERY_URL = "http://t.bomman.com/api/oksht-external/v2/product/search";
    private static final String AUTH_HEADER = "Basic c2FiZXI6c2FiZXJfc2VjcmV0";
    private static final String BODY_PARAMS = "account=kingbrother&password=6046B485926D49A3977E50BB80D5783B";

    @Resource
    private ComponentStockService componentStockService;

    @Resource
    private ComponentPriceService componentPriceService;

    @Resource
    private CallLimitService callLimitService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private SalePriceConfigServiceImpl salePriceConfigService;

    @Resource
    private HttpRequestLogService httpRequestLogService;

    /**
     * 获取令牌，优先从Redis获取，不存在则更新
     */
    public String getToken() {
        String token = stringRedisTemplate.opsForValue().get(TOKEN_KEY);
        return StringUtils.isNotBlank(token) ? token : updateToken();
    }

    /**
     * 更新令牌并存储到Redis
     */
    public String updateToken() {
        try (HttpResponse response = HttpRequest.post(TOKEN_URL)
                .header("Authorization", AUTH_HEADER)
                .body(BODY_PARAMS)
                .execute()) {

            String responseBody = response.body();
            httpRequestLogService.saveHttpRequestLog(QUERY_URL, "sht_token", BODY_PARAMS, response.body(), response.getStatus());
            JSONObject jsonResponse = JSONUtil.parseObj(responseBody);

            if (jsonResponse.getInt("code") == 200) {
                JSONObject data = jsonResponse.getJSONObject("data");
                String accessToken = data.getStr("accessToken");
                Long expire = data.getLong("expiresIn");

                stringRedisTemplate.opsForValue().set(TOKEN_KEY, accessToken, expire - 6000, TimeUnit.SECONDS);
                return accessToken;
            } else {
                log.error("更新令牌失败，响应: {}", responseBody);
                MessageUtil.sentMessage("26827", "圣禾堂更新令牌失败" + responseBody, "圣禾堂更新令牌失败");
            }
        } catch (Exception e) {
            log.error("更新令牌发生异常", e);
            MessageUtil.sentMessage("26827", "圣禾堂更新令牌异常" + e.getMessage(), "圣禾堂更新令牌异常");
        }
        return null;
    }

    /**
     * 单个型号查询
     */
    public List<ComponentPrice> queryOne(String model, String currency, Map<String, BigDecimal> componentSupplierMap) {
        String token = getToken();
        if (token == null) {
            log.error("获取令牌失败，无法执行查询");
            MessageUtil.sentMessage("26827", "圣禾堂获取令牌失败", "圣禾堂获取令牌失败");
            return new ArrayList<>();
        }

        try {
            callLimitService.supplierLimitCall(SupplierCodeEnum.SHT.getCode());
            String requestBody = buildRequestBody(model);
            String responseBody = executeQueryRequest(token, requestBody);
            log.info("{} 圣禾堂 queryOne API response: {}", model, responseBody);

            if (responseBody != null) {
                return processQueryResponse(responseBody, currency, componentSupplierMap, model);
            }
        } catch (Exception e) {
            log.error("查询型号[{}]失败", model, e);
            MessageUtil.sentMessage("26827", "圣禾堂查询型号异常" + e.getMessage(), "圣禾堂查询型号异常");
        }
        return new ArrayList<>();
    }

    /**
     * 批量型号查询
     */
    public void query(List<String> models, String currency, Map<String, BigDecimal> componentSupplierMap) {
        for (String model : models) {
            queryOne(model, currency, componentSupplierMap);
        }
    }

    /**
     * 构建查询请求体
     */
    private String buildRequestBody(String model) {
        return String.format("{\"keyword\": \"%s\", \"current\": 1, \"size\": 2000, \"type\": 1}", model);
    }

    /**
     * 执行查询请求
     */
    /**
     * 执行查询请求
     */
    private String executeQueryRequest(String token, String requestBody) {
        // 定义最大重试次数
        int maxRetries = 2;
        // 当前重试次数
        int retryCount = 0;

        while (retryCount <= maxRetries) {
            try {
                // 执行HTTP请求（添加超时设置，与原queryOne保持一致）
                try (HttpResponse response = HttpRequest.post(QUERY_URL)
                        .header("Blade-Auth", "bearer " + token)
                        .header("sht-auth", "external-service")
                        .body(requestBody)
                        .timeout(8000) // 统一超时设置为8秒
                        .execute()) {

                    httpRequestLogService.saveHttpRequestLog(QUERY_URL, "sht_queryOne", requestBody, response.body(), response.getStatus());
                    String responseBody = response.body();
                    log.info("sht queryOne API response: {}", responseBody);

                    // 解析响应JSON
                    com.alibaba.fastjson.JSONObject jsonResponse = JSON.parseObject(responseBody);
                    int code = jsonResponse.getIntValue("code");

                    // 判断是否为429需要重试
                    if (code == 429) {
                        if (retryCount < maxRetries) {
                            retryCount++;
                            log.info("Received 429 status code, retrying sht query (retry {}/{})", retryCount, maxRetries);
                            // 重试前延迟1秒，避免频繁请求
                            Thread.sleep(1000);
                            continue; // 继续下一次重试
                        } else {
                            log.warn("Max retries reached for 429 status code, returning last response");
                            return responseBody;
                        }
                    }

                    // 非429状态码，直接返回结果
                    return responseBody;
                }
            } catch (com.alibaba.fastjson.JSONException e) {
                log.error("JSON parse failed during sht query (retry count: {})", retryCount, e);
                // JSON解析异常不重试，直接退出循环
                break;
            } catch (Exception e) {
                log.error("Error occurred while executing sht query (retry count: {})", retryCount, e);

                // 检查是否为需要重试的超时异常
                if (e.getMessage() != null &&
                        (e.getMessage().contains("Connect timed out") ||
                                e.getMessage().contains("Connection timed out") ||
                                e.getMessage().contains("Read timed out")) &&
                        retryCount < maxRetries) {

                    retryCount++;
                    log.info("Retrying due to timeout (retry {}/{})", retryCount, maxRetries);
                    try {
                        Thread.sleep(1000); // 重试延迟
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                        break; // 线程被中断，停止重试
                    }
                } else {
                    // 非重试异常或达到最大重试次数，停止重试
                    break;
                }
            }
        }

        // 所有重试失败或无需重试时返回null
        return null;
    }

    /**
     * 处理查询响应
     */
    private List<ComponentPrice> processQueryResponse(String responseBody, String currency,
                                                      Map<String, BigDecimal> componentSupplierMap, String model) {

        com.alibaba.fastjson.JSONObject jsonResponse = JSON.parseObject(responseBody);
        if (jsonResponse.getIntValue("code") != 200) {
            log.warn("查询响应状态异常: {}", responseBody);
            MessageUtil.sentMessage("26827", "圣禾堂查询型号失败" + responseBody, "圣禾堂查询型号失败");
            return new ArrayList<>();
        }

        com.alibaba.fastjson.JSONObject dataObject = jsonResponse.getJSONObject("data");
        if (dataObject == null) {
            log.warn("查询响应数据为空: {}", responseBody);
            return new ArrayList<>();
        }

        JSONArray data = dataObject.getJSONArray("data");
        if (data == null || data.isEmpty()) {
            log.info("未查询到数据");
            return new ArrayList<>();
        }
        List<ComponentPrice> componentPriceList = new ArrayList<>();
        for (int i = 0; i < data.size(); i++) {
            com.alibaba.fastjson.JSONObject item = data.getJSONObject(i);
            ComponentPrice componentPrice = processItem(item, currency, componentSupplierMap, model);
            componentPriceList.add(componentPrice);
        }
        return componentPriceList;
    }

    /**
     * 处理单个查询结果项
     */
    private ComponentPrice processItem(com.alibaba.fastjson.JSONObject item, String currency,
                                       Map<String, BigDecimal> componentSupplierMap, String model) {

        // 创建库存对象
        ComponentStock stock = new ComponentStock();
        stock.setModel(item.getString("modelName"));
        stock.setBrand(item.getString("brandName"));
        stock.setSpecifications(item.getString("description"));
        stock.setPartnumber(item.getString("goodsSn"));
        stock.setKeyword(model);
        stock.setMinNum(StringUtils.isEmpty(item.getString("moq")) ? null :
                Integer.valueOf(item.getString("moq")));
        stock.setStockType(1);
        stock.setSupplierCode(SupplierCodeEnum.SHT.getCode());
        stock.setUniqueId(SupplierCodeEnum.SHT.getCode() + "_" + item.getString("goodsSn"));
        // 处理价格数组
        JSONArray priceArray = getPriceArrayByCurrency(item, currency);
        JSONArray resultArray = processPriceArray(priceArray, currency);
        componentStockService.saveComponentStockOfUniqueKey(stock);
        ComponentPrice componentPrice = createComponentPrice(stock.getUniqueId(), item, resultArray, currency, componentSupplierMap);
        componentPrice.setStockInfo(stock);
        return componentPrice;
    }

    /**
     * 根据货币类型获取价格数组
     */
    private JSONArray getPriceArrayByCurrency(com.alibaba.fastjson.JSONObject item, String currency) {
        return "USD".equals(currency)
                ? item.getJSONArray("priceStagesCNUSD")
                : item.getJSONArray("priceStagesRMBTax");
    }

    /**
     * 处理价格数组，格式化价格信息
     */
    private JSONArray processPriceArray(JSONArray priceArray, String currency) {
        JSONArray resultArray = new JSONArray();
        if (priceArray == null) return resultArray;

        for (int k = 0; k < priceArray.size(); k++) {
            com.alibaba.fastjson.JSONObject priceItem = priceArray.getJSONObject(k);
            BigDecimal price = priceItem.getBigDecimal("ladderTaxPrice");
            if (price == null) continue;

            BigDecimal roundedPrice = price.setScale(4, RoundingMode.HALF_UP);
            Integer quantity = priceItem.getInteger("ladderNumber");

            JSONObject priceInfo = new JSONObject();
            priceInfo.put("Price", roundedPrice.toString());
            priceInfo.put("Currency", currency);
            priceInfo.put("Quantity", quantity != null ? quantity.toString() : "0");

            resultArray.add(priceInfo);
        }
        return resultArray;
    }

    /**
     * 创建组件价格记录
     */
    private ComponentPrice createComponentPrice(String uniqueId, com.alibaba.fastjson.JSONObject item,
                                                JSONArray resultArray, String currency,
                                                Map<String, BigDecimal> componentSupplierMap) {

        String saleJson = salePriceConfigService.getSaleJson(
                resultArray.toJSONString(),
                item.getString("modelName"),
                currency
        );

        ComponentPrice componentPrice = new ComponentPrice(
                uniqueId,
                resultArray.toJSONString(),
                item.getLong("stockNum"),
                null,
                item.getString("encapsulationValue"),
                currency,
                item.getString("modelName"),
                resultArray.toJSONString(),
                saleJson,
                componentSupplierMap.getOrDefault(SupplierCodeEnum.SHT.getCode(), BigDecimal.valueOf(2))
        );

        componentPriceService.createComponentPriceOfUniqueKey(componentPrice);
        return componentPrice;
    }
}
